import fs from "fs";
import path from "path";
import pdb from "src/db/project";
import sdb from "src/db/snapshot";
import res from "src/utils/response";
import {
  gitLog,
  gitClone,
  runCommand,
  deployment,
  rollback,
  getDeployParams,
} from "src/utils";

export async function clone(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  const clonePath = path.join(row.install_path, row.project_name);
  if (row && row.del_flag === 1) {
    if (row.git_clone_status === 1 || fs.existsSync(clonePath)) {
      ctx.body = res.ok("该项目已克隆");
    } else {
      const url = row.repository_address;
      const branch = row.git_branch_name;
      const path = row.install_path;
      try {
        await gitClone(url, branch, path);
        await pdb.modify({ git_clone_status: 1, id: row.id });
        ctx.body = res.ok("项目克隆成功");
      } catch (error) {
        ctx.body = res.fail(error as API.ResponseError);
      }
    }
  } else {
    ctx.body = res.fail("不存在该项目");
  }
}

export async function pull(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  if (row && row.del_flag === 1) {
    if (row.git_clone_status === 1) {
      try {
        await runCommand("git pull", row.install_path);
        ctx.body = res.ok("项目更新完成");
      } catch (error) {
        ctx.body = res.fail(error as API.ResponseError);
      }
    } else {
      ctx.body = res.fail("该项目还未克隆");
    }
  } else {
    ctx.body = res.fail("不存在该项目");
  }
}

export async function install(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  if (row && row.del_flag === 1) {
    try {
      await runCommand(row.install_command, row.install_path);
      await pdb.modify({ install_status: 1, id: row.id });
      ctx.body = res.ok("项目安装成功");
    } catch (error) {
      ctx.body = res.fail(error as API.ResponseError);
    }
  } else {
    ctx.body = res.fail("不存在该项目");
  }
}

export async function build(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  if (row && row.del_flag === 1) {
    if (row.git_clone_status === 0) {
      ctx.body = res.fail("该项目还未克隆，不能构建");
      return;
    }
    if (row.install_status === 0) {
      ctx.body = res.fail("该项目还未安装，不能构建");
      return;
    }
    const buildProject = async () => {
      const { build_command, install_path } = row;
      const startTime = Date.now();
      await runCommand(build_command, install_path);
      const endTime = Date.now();
      const resTime = endTime - startTime;
      return resTime;
    };
    const buildAdd = async (latestLogId: string) => {
      delete params.id;
      const resTime = await buildProject();
      await pdb.modify({ git_commit_id: latestLogId, id: row.id });
      await sdb.add({
        ...params,
        git_commit_id: latestLogId,
        build_duration: resTime,
        snapshot_status: 0,
        project_id: row.id,
      });
    };
    const buildModify = async (latestLogId: string, srow: any) => {
      const resTime = await buildProject();
      await pdb.modify({ git_commit_id: latestLogId, id: row.id });
      await sdb.modify({
        ...params,
        git_commit_id: latestLogId,
        build_duration: resTime,
        snapshot_status: 0,
        del_flag: 1,
        id: srow.id,
      });
    };
    const buildQueryOne = async (git_commit_id: string) => {
      return await sdb.queryOne({ git_commit_id }, "git_commit_id");
    };
    try {
      const latestLogId = params.git_commit_id;
      if (row.git_commit_id) {
        const srow: any = await buildQueryOne(latestLogId);
        if (srow) {
          if (srow.del_flag === 1) {
            ctx.body = res.fail("当前构建已是最新的");
            return;
          } else {
            await buildModify(latestLogId, srow);
          }
        } else {
          await buildAdd(latestLogId);
        }
      } else {
        await buildAdd(latestLogId);
      }
    } catch (error) {
      ctx.body = res.fail(error as API.ResponseError);
      return;
    }
    ctx.body = res.ok("项目构建成功");
  } else {
    ctx.body = res.fail("不存在该项目");
  }
}

export async function deploy(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  const deployProject = async (git_commit_id: string) => {
    const startTime = Date.now();
    const deployParams = getDeployParams(row, git_commit_id);
    await deployment(deployParams);
    const endTime = Date.now();
    const resTime = endTime - startTime;
    return resTime;
  };
  const deployModify = async (srow: any) => {
    const resTime = await deployProject(srow.git_commit_id);
    delete params.snapshot_id;
    await sdb.batchModify(
      { snapshot_status: 1 },
      {
        del_flag: 1,
        snapshot_status: 2,
      }
    );
    await sdb.modify({
      ...params,
      deploy_duration: resTime,
      snapshot_status: 2,
      del_flag: 1,
      id: srow.id,
    });
  };
  if (row.git_commit_id) {
    try {
      const srow: any = await sdb.queryOne({ id: params.snapshot_id }, "id");
      if (srow) {
        if (srow.snapshot_status === 0) {
          await deployModify(srow);
          ctx.body = res.ok("项目部署成功");
        } else {
          ctx.body = res.ok("该项目已部署");
        }
      } else {
        ctx.body = res.fail("该快照尚未构建，不能部署");
      }
    } catch (error) {
      ctx.body = res.fail(error as API.ResponseError);
    }
  } else {
    ctx.body = res.fail("该项目尚未构建，不能部署");
  }
}

export async function rewind(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  const srow: any = await sdb.queryOne({ id: params.snapshot_id }, "id");
  try {
    if (srow) {
      if (srow.snapshot_status !== 0) {
        const deployParams = getDeployParams(row, srow.git_commit_id);
        await rollback(deployParams);
        await sdb.batchModify(
          { snapshot_status: 1 },
          {
            del_flag: 1,
            snapshot_status: 2,
          }
        );
        await sdb.modify({
          snapshot_status: 2,
          del_flag: 1,
          id: srow.id,
        });
        ctx.body = res.ok("项目回滚成功");
      } else {
        ctx.body = res.fail("该项目尚未部署");
      }
    } else {
      ctx.body = res.fail("该项目尚未构建，不能部署");
    }
  } catch (error) {
    ctx.body = res.fail(error as API.ResponseError);
  }
}

export async function gitlog(ctx: Context, params: any) {
  const row: any = await pdb.queryOne(params, "id");
  const log = await gitLog(
    { baseDir: row.install_path },
    params.page_index,
    params.page_size
  );
  ctx.body = res.ok(log);
}
